4.2 交换范式
4.2.1 简介
FHIR被设计成一种接口规范,它指定了医疗应用程序之间数据交换的内容与方法,以及如何实现和管理这种交换。目前FHIR支持五种互操作性范式来实现资源交换,分别是RESTful API、消息交换、文档交换、服务交换以及数据库/持久化存储。通过这些互操作范式,构建标准化的交换,降低系统之间连接和理解的成本。
五种范式每一种都可以用来交换信息,并且每种方法都有自己的优点和缺点以及适用性,但在实际应用中没有绝对的原则,一个系统可以支持多种范式组合实现。实现者具体使用时可根据自己的应用体系架构、企业现有能力来作为因素考量,考虑选择哪种合适的数据交换方式。
4.2.2 RESTful API
RESTful API是当前最流行的数据交互方式,是FHIR标准的核心。它提供了简单的、开箱即用的互操作性。在当前的互联网、物联网、云计算、移动端上都得到了广泛的应用。REST(Representational State Transfer)中文为“表述性状态转换”,利用Web标准中的一些准则和约束,充分地利用 HTTP 协议的各种功能,让应用软件应用变得更简洁,更有层次,增强可维护性。
FHIR中的RESTful API是一组明确定义的规范,支持XML、JSON等主流的数据交换格式,支持创建、读取、更新和删除的CRUD操作,以及搜索和执行操作,是FHIR交互资源的核心能力。FHIR中的RESTful API的基本交换定义如下:
VERB [base]/[type]{/[id]}{?_format=[mime-type]}
- VERB是HTTP请求动词,如GET、POST等
- 用[]括起来的内容是必须的,并将替换为表示的字符串文本
- base是是服务器的基础地址
- type是资源类型的名称,比如“Patient”
- id是资源的逻辑唯一号
- 用{}括起来的内容是可选的,表示资源的条件参数
- mime-type是application/fhir+xml或者application/fhir+json两种数据格式
FHIR支持的交换方式如下表所示,详情请见官网。
| 交互 | 路径 | 请求 | ||||
|---|---|---|---|---|---|---|
| Verb | Content-Type | Body | Prefer | Conditional | ||
| read | /[type]/[id] | GET | N/A | N/A | N/A | O: ETag,If-Modified-Since,If-None-Match |
| vread | /[type]/[id]/_history/[vid] | GET | N/A | N/A | N/A | N/A |
| update | /[type]/[id] | PUT | R | Resource | O | O: If-Match |
| patch | /[type]/[id] | PATCH | R (may be a patch type) | Patch | O | O: If-Match |
| delete | /[type]/[id] | DELETE | N/A | N/A | N/A | N/A |
| create | /[type] | POST | R | Resource | O | O: If-None-Exist |
| search | /[type]? | GET | N/A | N/A | N/A | N/A |
| /[type]/_search? | POST | application/x-www-form-urlencoded | form data | N/A | N/A | |
| search-all | ? | GET | N/A | N/A | N/A | N/A |
| capabilities | /metadata | GET | N/A | N/A | N/A | N/A |
| transaction | / | POST | R | Bundle | O | N/A |
| history | /[type]/[id]/_history | GET | N/A | N/A | N/A | N/A |
| history-type | /[type]/_history | GET | N/A | N/A | N/A | N/A |
| history-all | /_history | GET | N/A | N/A | N/A | N/A |
| (operation) | /$[name],/[type]/$[name]or /[type]/[id]/$[name] | POST | R | Parameters | N/A | N/A |
| GET | N/A | N/A | N/A | N/A | ||
| POST | application/x-www-form-urlencoded | form data | N/A | N/A |
说明:N/A =不存在,R =必需的,O =可选的
另外,我们可以连接FHIR公用服务器进行REST API验证测试,比如常用的公共 FHIR 服务器 UHN_HAPI Server (R4 FHIR),其地址为http://hapi.fhir.org

这里我们以Patient资源为例,来看下基本的CRUD 操作接口(创建、读取、读取历史、检索、更新 和删除)中创建患者的操作场景实例。
XML 样例如下:
<?xml version="1.0" encoding="UTF-8"?>
<Patient xmlns="http://hl7.org/fhir">
<id value="10001"/>
<!--患者身份证号-->
<identifier>
<system value="urn:oid:2.16.840.1.113883.2.23.1.9.1"/>
<value value="110101200301120033"/>
</identifier>
<!--患者社保卡号-->
<identifier>
<system value="urn:oid:2.16.840.1.113883.2.23.1.9.2"/>
<value value="100000000003"/>
</identifier>
<!--姓名-->
<name>
<text value="王康"/>
<family value="王"/>
<given value="康"/>
<!--可以只提供text字段而不提供family和given-->
</name>
<!--联系电话-->
<telecom>
<system value="phone"/>
<value value="13800138001"/>
<use value="mobile"/>
</telecom>
<!--性别-->
<gender value="male"/>
<!--出生日期,时间-->
<birthDate value="2003-01-12">
<extension url="http://hl7.org/fhir/StructureDefinition/patient-birthTime">
<valueDateTime value="2003-01-12T09:12:35+08:00"/>
</extension>
</birthDate>
<!--家庭住址-->
<address>
<use value="home"/>
<text value="北京市东城区景山前街8号"/>
<line value="景山前街8号"/>
<city value="北京市"/>
<district value="东城区"/>
<state value="北京"/>
<postalCode value="100010"/>
</address>
<!--联系人信息-->
<contact>
<relationship>
<coding>
<system value="http://hl7.org/fhir/patient-contact-relationship"/>
<code value="parent"/>
</coding>
</relationship>
<name>
<text value="王勇"/>
</name>
<telecom>
<system value="phone"/>
<value value="18612345678"/>
</telecom>
<gender value="male"/>
</contact>
</Patient>
1)患者注册
测试动作:客户端创建一个患者并调用Create 服务接口,将患者资源存储在服务器上。服务器分配患者资源 ID。
前置条件:测试前,该患者未在服务器注册。
验证标准:患者在服务器上创建成功且正确(可通过浏览器查看患者信息),则客户端需要能够从服务器的响应中或者通过患者查询接口获得服务器分配的患者 ID。
如下图所示,在Patient资源页面CRUD操作项中将资源xml放入Create的Contents文本框,点击Create按钮向服务器发送请求。

接收来自服务器的响应,HTTP状态为201表示创建成功,信息如下。

2)患者查询
通过使用患者的身份证号进行Search查询操作来获取服务器分配的患者资源ID,如下图所示。

成功获取到患者的资源ID。如下图,ID=2936702

另外我们也可以安装REST客户端工具来进行测试,比如参考http://wiki.hl7.org.cn:81/index.php?title=FHIR工作组 页面,根据该页面中的文档在火狐浏览器上安装RESTClient插件来测试。同时我们也能在此页面了解国内每年举行的“FHIR Connectathon连通测试大会”中用到的实际相关的核心临床资源的测试用例。

其他用于测试的公开可用的 FHIR 服务器可参见Publicly Available FHIR Servers for testing
该页面列出了全球范围内可公开用于测试的 FHIR服务器的集合,这些都是全世界的志愿者提供的公共服务。但我们需要注意的一点,这些测试服务器可能偶尔会不可用,并且由于FHIR 规范仍然在持续发展,它们可能并不总是按照FHIR标准的最新版本来实现的。

4.2.3 消息
FHIR不仅支持针对资源的RESTful API操作,还支持类似于HL7 V2消息的基于事件的消息交互范式。
在FHIR中,当事件发生时,一个“请求消息”将从源应用程序发送到目标应用程序,请求信息内容放置在一个名为Bundle的资源中。Bundle中通过type value="message"来标识为消息交换,Bundle中包含的第一个资源是FHIR中的MessageHeader资源,MessageHeader资源中使用一个名称为event[x]的节点来标识出请求消息事件的性质,同时MessageHeader中还携带了其他的请求元数据。消息结构如下图所示。

目标应用程序接收到请求后进行处理并返回一个或多个响应消息,这些响应消息也是一个由type value="message"标识的Bundle组成。Bundle包中的第一个资源同样也是MessageHeader资源,该资源中存在一个响应部分,该部分具体描述了消息处理的结果并包含了所需的任何其他的响应资源。
总之,消息交互是事件驱动型的,并且可以是异步的。通常它应用在需要请求/响应的工作流程中、或者需要在单个资源上驱动比CRUD更为复杂的行为,例如合并、复杂的查询操作以及需要异步通信、跨平台通信或者需要在尽量少的次数交换中能够传达多个资源的信息等场景下。
4.2.4 文档
文档交换是另外一种常见的互操作范式。有别于基于临床事件的消息交互范式,文档类似于我们常见的CDA,它是一组连贯的信息,由若干捆绑在一起的资源所构成的集合,是一组具有固定表示形式的不可变资源。以这种方式构建的文档可以在系统之间、机构之间进行交换,并在文档存储和管理系统中持久化保存。
文档交换中信息内容同样放置在Bundle资源中,它通过type value="document"来标识为文档交换。每个Bundle资源包中首先有一个“Composition ”资源作为包中的第一个资源,它是文档的基础,主要用来提供文档标识及其用途,并设置文档的上下文。同时包含了文档中的关键信息,例如文档关联的人和文档作者,以及文档的证明人等。然后是一系列从Composition 资源中引用的其他资源,这些资源一起为文档提供支持证据。文档结构如下图所示:

文档交换的应用场景比较适合于需要永久存储的静态数据、不涉及工作流的跨临床管理边界的临床信息交换,通常我们拿来用于机构之间的数据交换,比如临床中常见的入院记录、病程记录、手术记录、出院小结等这种阶段性的、小结性的、完整的医疗记录信息就特别适合使用文档交换的互操作范式。
4.2.5 服务
服务交换是FHIR提供的第四种范式,虽然FHIR资源主要是为基于RESTful HTTP的实现而设计的,但在交换资源时不一定必须使用RESTful接口,交换它们的一种方式可以在服务上下文环境中。服务是封装好的应用系统的功能,通过调用接口和定义良好的服务契约来交换信息(作为参数和输出)进行通信。
基于服务交互的互操作,需要双方规范互操作的业务流程和角色。服务交互通常是基于面向服务的这种架构、通过服务总线来进行交互的。服务是基于规范的业务流程、角色的,但是在医疗行业并不是所有的医疗流程都已经或者是能够规范的,所以服务交互目前来看还是有一定的适用范围。一般来说,当客户机应用程序存在有多步骤或复杂的处理需求时,特别是当这些事件涉及到复杂或动态流程的编排时,SOA技术和模式可以根据上下文环境对流程进行调整,提供良好的解决方案。例如IHE已经有了大量的场景规范基于FHIR来实现了。
4.2.6 数据库/持久化存储
最后一种互操作范式是数据仓库/持久化存储,FHIR可以使用支持JSON的经典关系型数据库或者NoSQL数据库(例如MongoDB,Couch,Hadoop或Big Query)以及一些基于 RDF存储的方式。通过这种“中间库”的方式实现FHIR资源的数据交互,将FHIR资源存储在本地数据库中或者持久性存储中,不同的应用程序或模块可以往数据库仓库中写入和读取资源。
资源数据仓库中存储了标准的FHIR资源,通过FHIR服务器对外提供标准的数据访问接口。这种模式目前在许多生产实现中都有应用,目前比较热门的SMART on FHIR就是采用的这种方式,基于底层的丰富FHIR资源数据仓库来支撑众多的微小医疗应用,实现“即插即用”的可用性。同时这种即插即用的医疗应用可以在所有支持FHIR的服务器和FHIR资源仓库上实现复用。